package com.km.team.phsystem.web.support;

import com.km.team.phsystem.common.enums.ResultEnum;
import com.km.team.phsystem.common.exception.SystemErrorException;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.SocketConfig;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 带有连接池特性的httpclient
 *
 * Created by jj02 on 2016/12/8.
 */
@Component
public class PoolingSimpleHttpClient {

    private CloseableHttpClient httpClient;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @PostConstruct
    public void init() {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setDefaultMaxPerRoute(200);	//每个主机的最大并行链接数
        cm.setMaxTotal(400);    //客户端总并行链接最大数

        SocketConfig socketConfig = SocketConfig.custom()
                .setSoKeepAlive(true)
                .setSoTimeout(3000)
                .build();

        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(10000)     //数据传输的最长时间
                .setConnectTimeout(3000)    // 创建连接的最长时间
                .setConnectionRequestTimeout(3000)  // 从连接池中获取到连接的最长时间
                .build();
        httpClient = HttpClients.custom()
                .setDefaultSocketConfig(socketConfig)
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(cm)
                .build();
    }

    public HttpResponse post(String url, List<NameValuePair> params, List<Header> headers) throws Exception{
        String body = null;
        HttpResponse response = null;
        try {
            // Post请求
            HttpPost httppost = new HttpPost(url);

            if(!CollectionUtils.isEmpty(headers)) {
                Header[] arr = new Header[headers.size()];
                headers.toArray(arr);
                httppost.setHeaders(arr);
            }

            // 设置参数
            httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
            // 发送请求
            response = this.httpClient.execute(httppost);
            return response;
        }catch (Exception e){
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());//会自动释放连接
                } catch (IOException e1) {
                    logger.error("关闭response异常！异常信息：" + e);
                }
                throw e;
            }
        }
        return null;
    }

    public HttpResponse postXML(String url, String postEntity, String charset) throws IOException {
        HttpPost post = new HttpPost(url);
        StringEntity entity = new StringEntity(postEntity, ContentType.create("text/xml",charset));
        post.setEntity(entity);
        CloseableHttpResponse response = null;
        try {
            response = this.httpClient.execute(post);
        } catch (IOException e) {
            throw e;
        }
        return response;
    }

    public HttpResponse post(String url, String postEntity, String charset, String contentType) throws IOException {
        HttpPost post = new HttpPost(url);
        StringEntity entity = new StringEntity(postEntity, ContentType.create(contentType,charset));
        post.setEntity(entity);
        CloseableHttpResponse response = null;
        try {
            response = this.httpClient.execute(post);
        } catch (IOException e) {
            throw e;
        }
        return response;
    }

    public HttpResponse postWithJson(String url, String json,String charset) throws IOException {
        HttpPost post = new HttpPost(url);
        post.setHeader("Content-type", "application/json");
        StringEntity entity = new StringEntity(json, charset);
        post.setEntity(entity);
        CloseableHttpResponse response = null;
        try {
            response = this.httpClient.execute(post);
        } catch (IOException e) {
            throw e;
        }
        return response;
    }

    public CloseableHttpResponse get(String url) throws IOException {
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = null;
        try{
            response = this.httpClient.execute(httpGet);
        }catch (Exception e){
            throw e;
        }
        return response;
    }

    public HttpResponse postForm(String url, Map<String,String> parameters) throws Exception {
        HttpPost httpPost = new HttpPost(url);
        List<BasicNameValuePair> values = new ArrayList<>();
        for(Map.Entry<String,String> entry : parameters.entrySet()){
            values.add(new BasicNameValuePair(entry.getKey(),entry.getValue()));
        }
        HttpEntity entity = new UrlEncodedFormEntity(values);
        httpPost.setEntity(entity);
        httpPost.setHeader("Connection","close");
        CloseableHttpResponse response = null;
        try{
            response = this.httpClient.execute(httpPost);
        }catch (Exception e){
            throw e;
        }
        return response;
    }

    public String postForm(String url, Map<String, String> content, String charset) throws IOException {
        HttpPost post = new HttpPost(url);
        List<BasicNameValuePair> values = new ArrayList<>();
        for (Map.Entry<String, String> entry : content.entrySet()) {
            values.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        HttpEntity entity = new UrlEncodedFormEntity(values, "utf-8");
//        StringEntity entity = new StringEntity(content, ContentType.create("application/json",charset));
        post.setEntity(entity);
        post.setHeader("Connection", "close");
        CloseableHttpResponse res = this.httpClient.execute(post);
        int statusCode = res.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            res.close();
            throw new IOException("error statusCode is " + statusCode);
        } else {
            String s = EntityUtils.toString(res.getEntity(), "utf-8");
            res.close();
            return s;
        }
    }
}
